L2norm

对输入向量进行 L2 归一化,并可选择性地应用 ReLU 或 ReLU6 激活函数。该算子首先用输入向量的 L2 范数(即欧几里得长度)去除向量中的每个元素,然后应用激活函数。

\[ \begin{align}\begin{aligned}S = \sqrt{\sum_{i=0}^{N-1} Input_i^2}\\\text{temp}_i = \frac{Input_i}{S}\\\begin{split}output_i = \begin{cases} \min(6, \max(0, \text{temp}_i)), & \text{if } \text{is\_relu6} = 1 \\ \max(0, \text{temp}_i), & \text{if } \text{is\_relu} = 1 \\ \text{temp}_i, & \text{otherwise} \end{cases}\end{split}\end{aligned}\end{align} \]
输入:
  • Input - 输入数据地址。

  • params - 参数打包成数组。
    • input_shape - 输入向量的shape。

    • temp_sum - 多核时每个核心计算的部分累加和。

    • shape_num - 输入维度数量。

    • element_num - 输入元素数量。

    • norm_flag - 0 表示全局归一化,1 表示按最后一个维度归一化, mindspore源码里面没有norm_flag,需要在接口部分自己计算

    • is_relu - 是否进行 ReLU 操作的标志(0或1)。

    • is_relu6 - 是否进行 ReLU6 操作的标志(0或1)。

    • &epsilon - 归一化因子,防止除0,这里传指针

  • core_mask - 核掩码(仅共享存储版本需要)。

输出:
  • Output - 计算结果地址。

支持平台:

FT78NE MT7004

备注

  • FT78NE 支持fp32

  • MT7004 支持fp16, fp32

共享存储版本:

void hp_l2norm_s(half *Input, half *output, long long *params, int core_mask)
void fp_l2norm_s(float *Input, float *output, long long *params, int core_mask)

C调用示例:

 1//FT78NE示例
 2#include <stdio.h>
 3#include <math.h>
 4#include <l2norm.h> // 假设头文件名为 l2norm.h
 5
 6int main(int argc, char* argv[]) {
 7    float* input = (float*)0x81000000;
 8    float* output = (float*)0x82000000;
 9
10    int input_shape[4] = {16, 8, 16, 8};
11    int is_relu = 1;
12    int is_relu6 = 1;
13    int norm_flag = 1; //0:全部norm,1:按最后一个维度norm
14    int shape_num = 4;
15    int element_num = input_shape[0] * input_shape[1] * input_shape[2] * input_shape[3];
16    float* temp_sum = (float*)0x10040000;
17    float epsilon = 1e-6;
18
19    srand(seed++);
20
21    int i;
22    for (i = 0; i < element_num; i++) {
23        input[i] = (float)(rand() % 20 + 1);
24    }
25
26    long long params[10];
27
28    params[0] = (long long)input_shape;
29    params[1] = (long long)temp_sum;
30    params[2] = (long long)shape_num;
31    params[3] = (long long)element_num;
32    params[4] = (long long)norm_flag;
33    params[5] = (long long)is_relu;
34    params[6] = (long long)is_relu6;
35    params[7] = (long long)&epsilon; //这里传指针
36
37    int core_mask = 0b1111;
38    fp_l2norm_s(input, output, (long long *)params, core_mask);
39    return 0;
40}

私有存储版本:

void hp_l2norm_p(half *Input, half *output, long long *params, int is_relu6)
void fp_l2norm_p(float *Input, float *output, long long *params)

C调用示例:

 1//FT78NE示例
 2#include <stdio.h>
 3#include <math.h>
 4#include <l2norm.h> // 假设头文件名为 l2norm.h
 5
 6int main(int argc, char* argv[]) {
 7    float* input = (float*)0x10010000;
 8    float* output = (float*)0x10020000;
 9
10    int input_shape[4] = {16, 8, 16, 8};
11    int is_relu = 1;
12    int is_relu6 = 1;
13    int norm_flag = 1; //0:全部norm,1:按最后一个维度norm
14    int shape_num = 4;
15    int element_num = input_shape[0] * input_shape[1] * input_shape[2] * input_shape[3];
16    float* temp_sum = (float*)0x10040000;
17    float epsilon = 1e-6;
18
19    srand(seed++);
20
21    int i;
22    for (i = 0; i < element_num; i++) {
23        input[i] = (float)(rand() % 20 + 1);
24    }
25
26    long long params[10];
27
28    params[0] = (long long)input_shape;
29    params[1] = (long long)temp_sum;
30    params[2] = (long long)shape_num;
31    params[3] = (long long)element_num;
32    params[4] = (long long)norm_flag;
33    params[5] = (long long)is_relu;
34    params[6] = (long long)is_relu6;
35    params[7] = (long long)&epsilon; //这里传指针
36
37    fp_l2norm_p(input, output, (long long *)params);
38    return 0;
39}